package cn.edu.qzuie.artist.module.td.service.teacher;

import cn.edu.qzuie.artist.framework.common.enums.UserTypeEnum;
import cn.edu.qzuie.artist.module.infra.api.config.ConfigApi;
import cn.edu.qzuie.artist.module.system.api.oauth2.OAuth2TokenApi;
import cn.edu.qzuie.artist.module.system.api.oauth2.dto.OAuth2AccessTokenCreateReqDTO;
import cn.edu.qzuie.artist.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO;
import cn.edu.qzuie.artist.module.system.enums.logger.LoginLogTypeEnum;
import cn.edu.qzuie.artist.module.system.enums.oauth2.OAuth2ClientConstants;
//import cn.edu.qzuie.artist.module.td.convert.auth.TeacherAuthConvert;

import cn.edu.qzuie.artist.module.td.controller.app.student.vo.AppStudentAuthLoginRepVo;
import cn.edu.qzuie.artist.module.td.controller.app.teacher.vo.AppTeacherAuthLoginRepVo;
import cn.edu.qzuie.artist.module.td.controller.app.teacher.vo.AppTeacherAuthLoginRespVo;
import cn.hutool.core.collection.CollUtil;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import cn.edu.qzuie.artist.module.td.controller.admin.teacher.vo.*;
import cn.edu.qzuie.artist.module.td.dal.dataobject.teacher.TeacherDO;
import cn.edu.qzuie.artist.framework.common.pojo.PageResult;
import cn.edu.qzuie.artist.framework.common.util.object.BeanUtils;

import cn.edu.qzuie.artist.module.td.dal.mysql.teacher.TeacherMapper;

import javax.annotation.Resource;
import javax.validation.Valid;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static cn.edu.qzuie.artist.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.edu.qzuie.artist.module.system.enums.ErrorCodeConstants.TEACHER_IMPORT_LIST_IS_EMPTY;
import static cn.edu.qzuie.artist.module.system.enums.ErrorCodeConstants.TEACHER_USERNAME_EXISTS;
import static cn.edu.qzuie.artist.module.td.enums.ErrorCodeConstants.*;

/**
 * 教师 Service 实现类
 *
 * @author 泉信管理员
 */
@Service
@Validated
public class TeacherServiceImpl implements TeacherService {

    @Resource
    private TeacherMapper teacherMapper;

    @Resource
    private OAuth2TokenApi oauth2TokenApi;

    @Resource
    private PasswordEncoder passwordEncoder;
    /**
     * 教师登录
     * @param reqVO 登录信息
     * @return
     */
    @Override
    public AppTeacherAuthLoginRepVo login(@Valid AppTeacherAuthLoginRespVo reqVO) {
        // 使用工号 + 密码，进行登录。
        TeacherDO teacher = login0(reqVO.getTeacherNo(), reqVO.getPassword());

        // 创建 Token 令牌
        return createTokenAfterLoginSuccess(teacher, reqVO.getTeacherNo(), reqVO.getTeacherId());
    }

    /**
     * 刷新令牌
     * @param refreshToken 刷新令牌
     * @return
     */

    @Override
    public AppTeacherAuthLoginRepVo refreshToken(String refreshToken) {
        OAuth2AccessTokenRespDTO accessTokenDO = oauth2TokenApi.refreshAccessToken(refreshToken,
                OAuth2ClientConstants.CLIENT_ID_DEFAULT);
        AppTeacherAuthLoginRepVo repVo = new AppTeacherAuthLoginRepVo();
        repVo.setTeacherId(accessTokenDO.getUserId());
        repVo.setRefreshToken(accessTokenDO.getRefreshToken());
        repVo.setExpiresTime(accessTokenDO.getExpiresTime());
        repVo.setAccessToken(accessTokenDO.getAccessToken());
        return repVo;
    }

    /**
     * 生成token
     * @param teacher
     * @return
     */
    private AppTeacherAuthLoginRepVo createTokenAfterLoginSuccess(TeacherDO teacher, String teacherNo,Long teacherId) {
        // 创建 Token 令牌
        OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.createAccessToken(new OAuth2AccessTokenCreateReqDTO()
                .setUserId(teacherId)
                .setUserType(getUserType().getValue())
                .setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT));


        // 手动组装构建返回结果
        AppTeacherAuthLoginRepVo repVo = new AppTeacherAuthLoginRepVo();
        repVo.setTeacherId(teacherId);
        repVo.setRefreshToken(accessTokenRespDTO.getRefreshToken());
        repVo.setExpiresTime(accessTokenRespDTO.getExpiresTime());
        repVo.setAccessToken(accessTokenRespDTO.getAccessToken());
        return repVo;
    }
    private TeacherDO login0(String teacherNo, String password) {
        // 校验账号是否存在
        TeacherDO teacher = teacherMapper.selectOne(new cn.edu.qzuie.artist.framework.mybatis.core.query.LambdaQueryWrapperX<TeacherDO>()
                .eq(TeacherDO::getTeacherNo, teacherNo)
                .eq(TeacherDO::getPassword, password));
        return teacher;
    }


    /**
     * 传身份ID
     * @return
     */

    private UserTypeEnum getUserType() {
        return UserTypeEnum.TEACHER;
    }


    @Override
    public Long createTeacher(TeacherSaveReqVO createReqVO) {
        // 插入
        TeacherDO teacher = BeanUtils.toBean(createReqVO, TeacherDO.class);
        teacherMapper.insert(teacher);
        // 返回
        return teacher.getId();
    }

    @Override
    public void updateTeacher(TeacherSaveReqVO updateReqVO) {
        // 校验存在
        validateTeacherExists(updateReqVO.getId());
        // 更新
        TeacherDO updateObj = BeanUtils.toBean(updateReqVO, TeacherDO.class);
        teacherMapper.updateById(updateObj);
    }

    @Override
    public void deleteTeacher(Long id) {
        // 校验存在
        validateTeacherExists(id);
        // 删除
        teacherMapper.deleteById(id);
    }

    private void validateTeacherExists(Long id) {
        if (teacherMapper.selectById(id) == null) {
            throw exception(TEACHER_NOT_EXISTS);
        }
    }

    @Override
    public TeacherDO getTeacher(Long id) {
        return teacherMapper.selectById(id);
    }

    @Override
    public PageResult<TeacherDO> getTeacherPage(TeacherPageReqVO pageReqVO) {
        return teacherMapper.selectPage(pageReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TeacherExcelRespVo batchInsertTeachers(List<TeacherExcelDataInputVO> importTeachers, boolean isUpdateSupport) {
        //1.1 参数校验（判断导入的数据是否为空）
        if(CollUtil.isEmpty(importTeachers)){
            throw exception(TEACHER_IMPORT_LIST_IS_EMPTY);
        }


        TeacherExcelRespVo respVo = TeacherExcelRespVo.builder()
                .createUsernames(new ArrayList<>())
                .updateUsernames(new ArrayList<>())
                .failureUsernames(new HashMap<>())
                .build();

        //1.2 参数校验（判断教师姓名是否填写完整）
        for (TeacherExcelDataInputVO importTeacher : importTeachers) {
            String realName = importTeacher.getRealName();
            if (realName == null || realName.isEmpty()) {
                throw exception(TEACHER_NOT_EXISTS);
            }

            //1.3 参数校验（判断教师已存在）
            TeacherDO existTeacher = teacherMapper.selectByTeacherNo(importTeacher.getTeacherNo());
            if (existTeacher == null) {
                // 若不存在，则插入新教师
                teacherMapper.insert(BeanUtils.toBean(importTeacher,TeacherDO.class).setPassword(encodePassword(importTeacher.getPassword())));
                respVo.getCreateUsernames().add(importTeacher.getRealName());
            }else {
                throw exception(TEACHER_USERNAME_EXISTS);
            }
        }
        return respVo;

    }

    /**
     * 对密码进行加密
     *
     * @param password 密码
     * @return 加密后的密码
     */
    private String encodePassword(String password) {
        return passwordEncoder.encode(password);
    }

}